package org.ii.infrastructure.flow.conversion;

import java.util.Collection;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.converters.Converter;
import org.springframework.binding.convert.service.DefaultConversionService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * Conversion service to be used with Spring Webflow. Extends Spring Webflows {@link DefaultConversionService}.
 * <p/>
 * Will automatically add all beans of type {@link Converter} annotated with {@link ConverterComponent} as converters which will
 * be available when binding in flows.
 * <p/>
 * The converters having a non blank value specified for {@link ConverterComponent#converterId()} will be added as custom
 * converters using {@link DefaultConversionService#addConverter(String, Converter)}.<br/>
 * The other converters will be added as default converters using {@link DefaultConversionService#addConverter(Converter)}.
 */
public class ConversionService extends DefaultConversionService implements ApplicationContextAware, InitializingBean {
	ApplicationContext applicationContext;

	public ConversionService() {
		super();
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		final Collection<Converter> converters = applicationContext.getBeansOfType(Converter.class).values();
		for (final Converter converter : converters) {
			final ConverterComponent annotation = converter.getClass().getAnnotation(ConverterComponent.class);
			if (annotation != null) {
				if (StringUtils.isNotBlank(annotation.converterId())) {
					super.addConverter(annotation.converterId(), converter);
				} else {
					super.addConverter(converter);
				}
			}
		}
	}

	@Override
	public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
}
